﻿
Imports System.Threading
Imports System.Net
Imports std
Imports storoomc

Public Module raserve
    Public Const defaultConfigfile As String = "raserve.ini"
    Public WithEvents server As processorHttpServer = Nothing

    Public Function selectStoroom(ByRef host As String, ByRef port As Int32) As Boolean
        assert(config.storoomhosts.size() > 0 AndAlso config.storoomhosts.size() = config.storoomports.size() _
               , "did not get required storoomhosts and storoomports in configuration.")

        If config.ignorecrawlingtag Then
            copy(host, config.storoomhosts(0))
            copy(port, config.storoomports(0))
            Return True
        Else
            Static lastaccess As Int64 = 0
            Static lasthost As String = Nothing
            Static lastport As Int32 = 0
            If Now.Ticks - lastaccess <= 10 * 60 * 1000 * 1000 _
                AndAlso Not isemptystring(lasthost) AndAlso lastport <> 0 Then
                copy(host, lasthost)
                copy(port, lastport)
                Return True
            Else
                Dim i As Int64
                For i = 0 To config.storoomhosts.size() - 1
                    If Not storoom.modify(rashare.crawling, Nothing) Then
                        copy(host, config.storoomhosts(i))
                        copy(port, config.storoomports(i))
                        copy(lasthost, host)
                        copy(lastport, port)
                        lastaccess = Now.Ticks()
                        Exit For
                    End If
                Next

                Return i < config.storoomhosts.size()
            End If
        End If
    End Function

    Public Function getstoroom(ByRef host As String, ByRef port As Int32, ByRef retrytimes As Int64) As Boolean
        If selectStoroom(host, port) Then
            retrytimes = config.storoomretrytimes
            Return True
        Else
            Return False
        End If
    End Function

    Public Sub start()
        If server Is Nothing Then
            server = New processorHttpServer()
        End If
        Dim pages As vector(Of requestProcessor) = Nothing
        pages = server.processors()
        assert(Not pages Is Nothing, "server.processors() is nothing.")
        If pages.size() = 0 Then
            pages.push_back(New staticrequest())
            pages.push_back(New buildInfoPage())
            pages.push_back(New favicon())
            pages.push_back(New inputpage())
            pages.push_back(New rssrequest())
            pages.push_back(New submitpage())
            pages.push_back(New searchpage())

            'this should always be at the end
            pages.push_back(New homepage())
        End If

        Dim i As Int64
        For i = 0 To pages.size() - 1
            pages(i).initial()
        Next

        storoom.initial(AddressOf getstoroom)

        server.addports(config.port)
        raiseError("server will start on port " + config.port)
        server.start()
    End Sub

    Public Sub monitor()
        While Not consoleExtSignal() AndAlso (config.configRefreshing() OrElse server.health())
            sleep()
        End While

        If consoleExtSignal() Then
            raiseError("caught console cancel key event, shutdown.")
        Else
            raiseError("httpServer2 failed, shutdown.", errorHandle.errorType.exclamation)
        End If
        shutdown()
    End Sub

    Public Sub shutdown()
        If Not server Is Nothing Then
            server.stop()
        End If
        forceQuit(0)
    End Sub

    Public Sub restart()
        shutdown()
        start()
    End Sub

    Public Sub unhandledException(ByVal ex As Exception)
        shutdown()
    End Sub

    Friend unhandledExceptionHandler As UnhandledExceptionDelegate = AddressOf unhandledException

    Public Sub main(ByVal args() As String)
        registerConsoleExtHandle()
        errorHandle.initial(defaultLogFilename())
        If Not isdebugmode() Then
            registerUnhandledException(unhandledExceptionHandler)
        End If
        destructor.start()

        Dim configfile As String = defaultConfigfile
        If args.Length() > 0 Then
            configfile = args(0)
        End If

        If Not config.open(configfile) Then
            raiseError("cannot load config file " + configfile, errorHandle.errorType.exclamation)
        Else
            raiseError("load configuration success, start service.")
            start()
            monitor()
        End If

        destructor.stop()
        errorHandle.finalize()
        consoleExtHandleFinish()
    End Sub

    Private Sub server_receive(ByVal context As httpContext) Handles server.receive
        assert(False, "processorHttpServer should not raise receive event.")
    End Sub
End Module
